﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Belyn.Common.Web;
using System.Threading;
using Cartoon.Model;
using System.Text.RegularExpressions;
using System.IO;
using Cartoon.Common;

namespace Cartoon.Logic
{
    public class CartoonDownload: IDownload
    {
        #region 属性 

        AutoResetEvent autoEventDownload = new AutoResetEvent(false);
        AutoResetEvent autoEventSpeed = new AutoResetEvent(false);
        protected long DownloadSpeed;
        protected string DownloadFileName;
        protected string DownloadTitle;
        protected bool DownloadOver;
        Thread thrSpeedTimer;
        Thread ThrSpeedTimer
        {
            get
            {
                if (this.thrSpeedTimer == null)
                {
                    this.thrSpeedTimer = new Thread(new ThreadStart(this.CountSpeed)); 
                } 
                return this.thrSpeedTimer;
            }
        }

        Thread thread_download; 
        Thread Thread_download
        {
            get 
            {
                if (this.thread_download == null)
                {
                    this.thread_download = new Thread(new ThreadStart(this.DownloadStart));
                    this.Thread_download.Priority = ThreadPriority.BelowNormal;
                }

                return this.thread_download;
            }
        }

        private object lock_thread_state = new object();
        private DownloadState _download_state;
        protected DownloadState Download_state
        {
            get
            {
                return this._download_state;
            }
            set
            {
                lock (this.lock_thread_state)
                {
                    this._download_state = value;
                }  
            }
        }

        public Chapter DownloadChapter { get; private set; }

        protected int PicCount
        {
            get { return this.DownloadChapter.PicListUrl == null ? 0 : this.DownloadChapter.PicListUrl.Count; }
        }

        protected int Download_PicIndex;
        protected ICartoonView CartoonView;
        protected CartoonViewerService CartoonService;
        #endregion 

        public CartoonDownload(Chapter _chp,ICartoonView _cartoonView)
        {
            this.DownloadChapter = _chp;
            this.Download_PicIndex = 0;
            this.CartoonView = _cartoonView;
            this.CartoonService = new CartoonViewerService();

            this.DownloadTitle = this.DownloadChapter.comic.Name + "第" + this.DownloadChapter.Id + "话";
            
            this.Download_state = DownloadState.Stop; 
        }


        protected string GetChapterFilePath()
        {
            return this.CartoonView.CartoonSavePath + "\\" + this.DownloadChapter.comic.Name + "\\" + this.DownloadChapter.Id + "\\Chapter.xml";
        }

        protected void GetPicUrls()
        {
            if (this.DownloadChapter.PicCount <= 1)
            {
                bool isExistsXml = false;

                Chapter xmlChp = this.DownloadChapter.Load(this.GetChapterFilePath());

                if (xmlChp.PicCount > 1)
                {
                    isExistsXml = true;
                    this.DownloadChapter.PicListUrl = xmlChp.PicListUrl;
                    this.DownloadChapter.PicAllSize = xmlChp.PicAllSize;
                    this.DownloadChapter.PicListUrlString = xmlChp.PicListUrlString;
                    this.DownloadChapter.PicCount = this.DownloadChapter.PicListUrl.Count;

                }

                if (isExistsXml == false)
                { 
                    string url = this.DownloadChapter.Src;
                    string htmlcode = "";
                    bool connected = false;
                    try
                    {
                        htmlcode = HttpRequest.GetHttpCode(url);
                        connected = true;
                    }
                    catch (Exception ex)
                    {
                        connected = false;
                        this.Download_state = DownloadState.Stop;
                        this.OnFailed(ex.Message);
                        
                    }

                    if (connected == true)
                    {
                        Regex rg = new Regex(this.DownloadChapter.comic.RegexExpForPicList,RegexOptions.IgnoreCase);
                        Match m = rg.Match(htmlcode);

                        string[] picSrcs = m.Groups[1].Value.Split('|');
                        this.DownloadChapter.PicListUrlString = m.Groups[1].Value;
                        this.DownloadChapter.PicCount = picSrcs.Count();
                        this.DownloadChapter.PicListUrl = picSrcs.ToList();

                        this.DownloadChapter.Save(this.GetChapterFilePath());
                    }
                }  

            }
            if (this.PicCount == 0)
            {
                return;
            }
             
        }
          
        protected void DownloadStart()
        {
            this.GetPicUrls();

            Chapter selChp = this.DownloadChapter;
            bool isFailed = false;
            string failedMessage = "";
            while (true)
            {
                if (this.Download_state == DownloadState.Suspend)
                {
                    try
                    {
                        this.OnSuspended();
                        this.autoEventDownload.WaitOne();
                        Thread.Sleep(2000);
                    }
                    catch (Exception ignore) { }
                    continue;
                }
                else if (this.Download_state == DownloadState.Stop)
                {
                    break;
                }


                string picSrc = selChp.PicListUrl[ this.Download_PicIndex ];

                string picUrl = selChp.comic.PictureDomain + picSrc;

                string picSavePath = this.CartoonView.CartoonSavePath + "\\" + selChp.comic.Name + "\\" + selChp.Id + "\\";
                if (Directory.Exists(picSavePath) == false)
                {
                    Directory.CreateDirectory(picSavePath);
                }

                this.DownloadFileName = "第" + this.DownloadChapter.Id + "话" + "的第" + (this.Download_PicIndex + 1) + "张" + " (共" + this.DownloadChapter.PicCount + "张)";

                try
                {
                    this.CartoonService.SaveImage(picUrl, this.DownloadChapter.comic.ChapterDomain, picSavePath + System.IO.Path.GetFileName(picUrl));
                }
                catch (Exception ex)
                {
                    Log.debug(this.DownloadFileName + "下载失败：" + ex.Message);
                    isFailed = true;
                    failedMessage = this.DownloadFileName + "下载失败：" + ex.Message;
                    break;
                }

                this.Download_PicIndex++;
                if (this.Download_PicIndex == this.PicCount)
                {
                    this.Download_state = DownloadState.Success;
                    this.DownloadOver = true;
                    this.OnDownloading(); 
                    
                    break;
                }

                this.OnDownloading(); 

            }

            if (isFailed == true)
            {
                this.OnFailed(failedMessage);
                this.Download_state = DownloadState.Stop;
                this.OnStoped();
            } 
        } 

        #region IDownload 成员

        public void Download()
        {
            if (this.Download_state == DownloadState.Suspend)
            {
                Log.log("继续下载 " + this.Title + " ...");
                this.Continue();

                return;
            }

            if (this.Download_state == DownloadState.Downloading)
            { return; }

            this.Download_state = DownloadState.Downloading;

            Log.log("开始下载 " + this.Title + " ...");
            if (this.Thread_download.ThreadState != ThreadState.Running)
            { 
                
                this.Thread_download.Start();
                this.OnStarted();
            }

            if (this.ThrSpeedTimer.ThreadState != ThreadState.Running)
            {
                this.ThrSpeedTimer.Start();
            }

        }

        public void Stop()
        {
            this.Cancel();
             
        }

        public void Continue()
        {
            this.Download_state = DownloadState.Downloading;
            this.autoEventDownload.Set();
            this.autoEventSpeed.Set();
        }

        public void Suspend()
        {
            Log.log("暂停下载 " + this.Title + " ...");
            this.Download_state = DownloadState.Suspend;
        }

        public void Cancel()
        {
            Log.log("取消下载 " + this.Title + " ...");
            this.Download_state = DownloadState.Stop;
            try
            {
                this.thread_download.Abort();

            }
            catch { }

            try
            {
                this.ThrSpeedTimer.Abort();
            }
            catch { }
             
            this.OnCanceled();

        }

        public double Progress
        {
            get 
            { 
                if (PicCount <= 0) return 0;
                if (this.Download_PicIndex == this.PicCount) return 1;
                return (double)this.Download_PicIndex / PicCount + this.CartoonService.Progress * 1/PicCount ; 
            }
        }

        public double Speed
        {
            get { return this.DownloadSpeed; }
        }
        public bool Over { get { return this.DownloadOver; } }

        public string FileName { get { return this.DownloadFileName; } }
        public string Title { get { return this.DownloadTitle; } }

        public DownloadState State { get { return this.Download_state; } }

        public event DownloadDelegate Downloading;

        public event DownloadDelegate Started;

        public event DownloadDelegate Stoped;

        public event DownloadDelegate Canceled;

        public event DownloadDelegate Suspended;

        public event DownloadDelegate SpeedChanged;

        public event DownloadFailedDelegate Failed;

        #endregion

        protected void OnCanceled()
        {
            if (this.Canceled != null)
            {
                this.Canceled(this);
            }
        }

        protected void OnDownloading()
        {
            if (this.Downloading != null)
            {
                this.Downloading(this);
            }
        }

        protected void OnStarted()
        {
            if (this.Started != null)
            {
                this.Started(this);
            }
        }
        protected void OnStoped()
        {
            if (this.Stoped != null)
            {
                this.Stoped(this);
            }
        }
        protected void OnSuspended()
        {
            if (this.Suspended != null)
            {
                this.Suspended(this);
            }
        }

        protected void OnSpeedChanged()
        {
            if (this.SpeedChanged != null)
            {
                this.SpeedChanged(this);
            }
        }

        protected void OnFailed(string message)
        {
            if (this.Failed != null)
            { 
                this.Failed(this, message);
            }
        }

        private long oldDataReaded = 0;
        private long newDataReaded = 0;
        private long oldDownloadSpeed = 0;
        protected void CountSpeed()
        {
            while (true)
            {
                bool speedChanged = false;
                if (this.Download_state == DownloadState.Suspend)
                {
                    try
                    {
                        this.autoEventSpeed.WaitOne();
                        Thread.Sleep(2000);
                    }
                    catch (Exception ignore) { }
                    continue;
                }
                else if (this.Download_state == DownloadState.Stop || this.Download_state == DownloadState.Success)
                {
                    break;
                }
                

                this.newDataReaded = this.CartoonService.DataReaded;
                this.DownloadSpeed = this.newDataReaded - this.oldDataReaded;
                this.oldDataReaded = this.newDataReaded;
                

                if(this.oldDownloadSpeed != this.DownloadSpeed)
                {
                    this.oldDownloadSpeed = this.DownloadSpeed;
                    speedChanged = true;
                }

                if (speedChanged == true)
                {
                    this.OnSpeedChanged();
                }

                //一秒算一次速度 
                try
                { 
                    Thread.Sleep(1000);
                }
                catch (Exception ignore)
                { }


            }
        }

    }
}
